--- /dev/null
+/* NOTE: This file split off from evtchn.c because there was
+ some discussion that the mechanism is sufficiently different.
+ It may be possible to merge it back in the future... djm */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/hw_irq.h>
+#include <asm-xen/evtchn.h>
+
+#define MAX_EVTCHN 256
+static struct {
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ void *dev_id;
+} evtchns[MAX_EVTCHN];
+
+int virq_to_evtchn[NR_VIRQS] = {-1};
+unsigned int bind_virq_to_evtchn(int virq)
+{
+ evtchn_op_t op;
+
+ op.cmd = EVTCHNOP_bind_virq;
+ op.u.bind_virq.virq = virq;
+ if ( HYPERVISOR_event_channel_op(&op) != 0 )
+ BUG();
+
+ virq_to_evtchn[virq] = op.u.bind_virq.port;
+ return op.u.bind_virq.port;
+}
+
+int bind_virq_to_irq(int virq)
+{
+ printk("bind_virq_to_irq called... FIXME??\n");
+ while(1);
+}
+
+void unbind_virq_from_evtchn(int virq)
+{
+ evtchn_op_t op;
+
+ op.cmd = EVTCHNOP_close;
+ op.u.close.dom = DOMID_SELF;
+ op.u.close.port = virq_to_evtchn[virq];
+ if ( HYPERVISOR_event_channel_op(&op) != 0 )
+ BUG();
+
+ virq_to_evtchn[virq] = -1;
+}
+
+int bind_evtchn_to_irqhandler(unsigned int evtchn,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
+{
+ if (evtchn >= MAX_EVTCHN)
+ return -EINVAL;
+
+ evtchns[evtchn].handler = handler;
+ evtchns[evtchn].dev_id = dev_id;
+ unmask_evtchn(evtchn);
+ return 0;
+}
+
+void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
+{
+ if (evtchn >= MAX_EVTCHN)
+ return;
+
+ mask_evtchn(evtchn);
+ evtchns[evtchn].handler = NULL;
+}
+
+void unbind_evtchn_from_irq(unsigned int evtchn)
+{
+ printk("unbind_evtchn_from_irq called... FIXME??\n");
+ while(1);
+}
+
+irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 l1, l2;
+ unsigned int l1i, l2i, port;
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
+
+ vcpu_info->evtchn_upcall_mask = 1;
+ vcpu_info->evtchn_upcall_pending = 0;
+
+ /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+ while ( l1 != 0 )
+ {
+ l1i = __ffs(l1);
+ l1 &= ~(1 << l1i);
+
+ while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
+ {
+ l2i = __ffs(l2);
+ l2 &= ~(1 << l2i);
+
+ port = (l1i << 5) + l2i;
+ if ( (handler = evtchns[port].handler) != NULL )
+ {
+ clear_evtchn(port);
+ handler(port, evtchns[port].dev_id, regs);
+ }
+ else
+ {
+ evtchn_device_upcall(port);
+ }
+ }
+ }
+ vcpu_info->evtchn_upcall_mask = 0;
+ return IRQ_HANDLED;
+}
+
+void force_evtchn_callback(void)
+{
+ //(void)HYPERVISOR_xen_version(0, NULL);
+}
+
+static struct irqaction evtchn_irqaction = {
+ .handler = evtchn_interrupt,
+ .flags = SA_INTERRUPT,
+ .name = "xen-event-channel"
+};
+
+int evtchn_irq = 0xe9;
+void __init evtchn_init(void)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
+
+#if 0
+ int ret;
+ irq = assign_irq_vector(AUTO_ASSIGN);
+ ret = request_irq(irq, evtchn_interrupt, 0, "xen-event-channel", NULL);
+ if (ret < 0)
+ {
+ printk("xen-event-channel unable to get irq %d (%d)\n", irq, ret);
+ return;
+ }
+#endif
+ register_percpu_irq(evtchn_irq, &evtchn_irqaction);
+
+ vcpu_info->arch.evtchn_vector = evtchn_irq;
+ printk("xen-event-channel using irq %d\n", evtchn_irq);
+}
+
+/* Following are set of interfaces unused on IA64/XEN, just keep it here */
+
+void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) {}
+int teardown_irq(unsigned int irq, struct irqaction * old) {return 0;}
--- /dev/null
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+#include <asm-xen/xen-public/xen.h>
+
+/* FIXME: temp place to hold these page related macros */
+#include <asm/page.h>
+#define virt_to_machine(v) __pa(v)
+#define machine_to_virt(m) __va(m)
+//#define virt_to_mfn(v) (__pa(v) >> 14)
+//#define mfn_to_virt(m) (__va(m << 14))
+#define virt_to_mfn(v) ((__pa(v)) >> PAGE_SHIFT)
+#define mfn_to_virt(m) (__va((m) << PAGE_SHIFT))
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+
+#if 0
+static inline int
+HYPERVISOR_set_trap_table(
+ trap_info_t *table)
+{
+#if 0
+ int ret;
+ unsigned long ignore;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ignore)
+ : "0" (__HYPERVISOR_set_trap_table), "1" (table)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+ unsigned long *frame_list, int entries)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
+ : "memory" );
+
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_stack_switch(
+ unsigned long ss, unsigned long esp)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
+ unsigned long event_selector, unsigned long event_address,
+ unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
+ "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+ int set)
+{
+#if 0
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_yield(
+ void)
+{
+#if 0
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_block(
+ void)
+{
+#if 0
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ void)
+{
+#if 0
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_reboot(
+ void)
+{
+#if 0
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ /* NB. On suspend, control software expects a suspend record in %esi. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=S" (ign2)
+ : "0" (__HYPERVISOR_sched_op),
+ "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
+ "S" (srec) : "memory");
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_crash(
+ void)
+{
+#if 0
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
+{
+#if 0
+ int ret;
+ unsigned long timeout_hi = (unsigned long)(timeout>>32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
+ : "memory");
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_dom0_op(
+ dom0_op_t *dom0_op)
+{
+#if 0
+ int ret;
+ unsigned long ign1;
+
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
+ : "memory");
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_set_debugreg(
+ int reg, unsigned long value)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline unsigned long
+HYPERVISOR_get_debugreg(
+ int reg)
+{
+#if 0
+ unsigned long ret;
+ unsigned long ign;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_update_descriptor(
+ unsigned long ma, unsigned long word1, unsigned long word2)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+ : "0" (__HYPERVISOR_update_descriptor), "1" (ma), "2" (word1),
+ "3" (word2)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_set_fast_trap(
+ int idx)
+{
+#if 0
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_dom_mem_op(
+ unsigned int op, unsigned long *extent_list,
+ unsigned long nr_extents, unsigned int extent_order)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4, ign5;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
+ "=D" (ign5)
+ : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
+ "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_multicall(
+ void *call_list, int nr_calls)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping(
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+ : "0" (__HYPERVISOR_update_va_mapping),
+ "1" (va), "2" ((new_val).pte_low), "3" (flags)
+ : "memory" );
+
+ if ( unlikely(ret < 0) )
+ {
+ printk(KERN_ALERT "Failed update VA mapping: %08lx, %08lx, %08lx\n",
+ va, (new_val).pte_low, flags);
+ BUG();
+ }
+
+ return ret;
+#endif
+ return 1;
+}
+#endif
+
+static inline int
+HYPERVISOR_event_channel_op(
+ void *op)
+{
+ int ret;
+ __asm__ __volatile__ ( ";; mov r14=%2 ; mov r2=%1 ; break 0x1000 ;; mov %0=r8 ;;"
+ : "=r" (ret)
+ : "i" (__HYPERVISOR_event_channel_op), "r"(op)
+ : "r14","r2","r8","memory" );
+ return ret;
+}
+
+#if 0
+static inline int
+HYPERVISOR_xen_version(
+ int cmd)
+{
+#if 0
+ int ret;
+ unsigned long ignore;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ignore)
+ : "0" (__HYPERVISOR_xen_version), "1" (cmd)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+#endif
+
+static inline int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str)
+{
+ int ret;
+ __asm__ __volatile__ ( ";; mov r14=%2 ; mov r15=%3 ; mov r16=%4 ; mov r2=%1 ; break 0x1000 ;; mov %0=r8 ;;"
+ : "=r" (ret)
+ : "i" (__HYPERVISOR_console_io), "r"(cmd), "r"(count), "r"(str)
+ : "r14","r15","r16","r2","r8","memory" );
+ return ret;
+}
+
+#if 0
+static inline int
+HYPERVISOR_physdev_op(
+ void *physdev_op)
+{
+#if 0
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+#endif
+
+static inline int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ int ret;
+ __asm__ __volatile__ ( ";; mov r14=%2 ; mov r15=%3 ; mov r16=%4 ; mov r2=%1 ; break 0x1000 ;; mov %0=r8 ;;"
+ : "=r" (ret)
+ : "i" (__HYPERVISOR_grant_table_op), "r"(cmd), "r"(uop), "r"(count)
+ : "r14","r15","r16","r2","r8","memory" );
+ return ret;
+}
+
+#if 0
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
+ "1" (va), "2" ((new_val).pte_low), "3" (flags), "4" (domid) :
+ "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_vm_assist(
+ unsigned int cmd, unsigned int type)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
+ : "memory" );
+
+ return ret;
+#endif
+ return 1;
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+#if 0
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
+ : "memory");
+
+ return ret;
+#endif
+ return 1;
+}
+#endif
+
+#endif /* __HYPERCALL_H__ */